package com.sky.aspect;

import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Aspect
@Slf4j
@Component
public class AutoFillAspect {
    @Pointcut("@annotation(com.sky.annotation.AutoFill)")
    public void autoFillPointcut(){}
    /**
     * 逻辑：
     * 1. 获取方法参数：即实体对象
     * 2. 获取当前时间
     * 3. 根据对应的操作类型，为对应的属性赋值
     *
     * @param joinPoint
     */
    @Before("autoFillPointcut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("开始进行数据填充");
        //拦截住了 添加/修改 连接点的参数对象
        //joinPoint 获取方法传递的参数
        Object[] args = joinPoint.getArgs();
        Object entry =args[0];

        //1.判断 当前拦截住的连接点对应的方法时更新还是添加
        //基于joinPoint获取到原始方法Method对象形式
        //1.1 获取方法签名
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //1.2 获取原始方法Method
        Method method = signature.getMethod();
        //1.3 解析方法上的注解
        AutoFill autoFill = method.getAnnotation(AutoFill.class);
        //1.4获取注解中的操作类型
        OperationType operationType = autoFill.value();
        log.info("可以分辨自动填充操作类型：{}", operationType);
        LocalDateTime now=LocalDateTime.now();
        Long currentId=BaseContext.getCurrentId();
        //如果是更新 完成 两个字段的设置 updateTime updateUser
        if(operationType == OperationType.INSERT){
            log.info("判断为新增");
            //新增-- 往参数对象设置两个属性 updateTime updateUser createTime createTime
            try{
                //添加时间
                Method setCreateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
                setCreateTime.invoke(entry, now);
                //创建人
                Method setCreateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
                setCreateUser.invoke(entry, currentId);
                //更新时间
                Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                setUpdateTime.invoke(entry, now);
                //更新人
                Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                setUpdateUser.invoke(entry, currentId);
            }catch(Exception e){
                log.info("没有对应的方法,或者权限不够无法运行");
                throw new RuntimeException(e);
            }
        }else{
            log.info("判断为更新");
            //更新-- 往参数对象设置四个属性 updateTime updateUser
            try{
                //更新时间
                Method setUpdateTime = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
                setUpdateTime.invoke(entry, now);
                //更新人
                Method setUpdateUser = entry.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
                setUpdateUser.invoke(entry, currentId);
            }catch(Exception e){
                log.info("没有对应方法,或者权限不够无法运行");
                throw new RuntimeException(e);
            }
        }
    }
}
